﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using MvcMembership;
using NLog;
using System.Net.Mail;
using planerka.DataAccess.ViewModels.UserAdministration;
using PagedList;
using planerka.Common.Enums;

namespace planerka.Web.Controllers
{
    [Authorize(Roles = "Administrator")]
    [HandleError(ExceptionType = typeof(DuplicateRoleException), View = "DuplicateRoleFound")]
    public class UserAdministrationController : Controller
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        private const int PageSize = 100;
        private const string ResetPasswordBody = "Ваш новый пароль: ";
        private const string ResetPasswordFromAddress = "from@domain.com";
        private const string ResetPasswordSubject = "Ваш новый пароль";
        private readonly IRolesService _rolesService;
        private readonly ISmtpClient _smtpClient;
        private readonly IUserService _userService;
        private readonly IPasswordService _passwordService;

        public UserAdministrationController()
            : this(
                new AspNetMembershipProviderWrapper(Membership.Provider),
                new AspNetMembershipProviderWrapper(Membership.Provider),
                new AspNetRoleProviderWrapper(Roles.Provider),
                new SmtpClientProxy(new SmtpClient()))
        {
        }

        public UserAdministrationController(
            IUserService userService,
            IPasswordService passwordService,
            IRolesService rolesService,
            ISmtpClient smtpClient)
        {

            _userService = userService;
            _passwordService = passwordService;
            _rolesService = rolesService;
            _smtpClient = smtpClient;


        }

        // вывести список пользователей
        public ViewResult Index(int? index)
        {
            var users = _userService.FindAll(index ?? 0, PageSize);
            var roles = _rolesService.FindAll();

            string roleFilter = "", loginFilter = "";
            // обработать фильтры

            if (Session["roleFilter"] != null)
            {
                roleFilter = Session["roleFilter"].ToString().Trim();
                if (roleFilter != "")
                {
                    List<MembershipUser> tempUsers = _rolesService.FindUserNamesByRole(roleFilter).Select(username => _userService.Get(username)).Where(p => p != null).ToList();
                    users = new StaticPagedList<MembershipUser>(tempUsers, index ?? 0, PageSize, tempUsers.Count);
                }
            }

            if (Session["loginFilter"] != null)
            {
                loginFilter = Session["loginFilter"].ToString().Trim();
                if (loginFilter != "")
                {
                    List<MembershipUser> tempUsers = users.Where(p => p.UserName.Contains(loginFilter)).ToList();
                    users = new StaticPagedList<MembershipUser>(tempUsers, index ?? 0, PageSize, tempUsers.Count);
                }
            }

            //
            if (roles.Distinct().Count() != roles.Count())
                throw new DuplicateRoleException("Список ролей содержит повторяющиеся значения.");

            return View(new IndexViewModel
            {
                Users = users,
                Roles = roles,
                loginFilter = loginFilter,
                roleFilter = roleFilter
            });
        }

        [HttpPost]
        public ActionResult refreshFilter(FormCollection formValues)
        {
            string roleFilter = formValues["roleFilter"].ToString();
            string loginFilter = formValues["loginFilter"].ToString();

            Session["roleFilter"] = roleFilter;
            Session["loginFilter"] = loginFilter;


            return RedirectToAction("Index");
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult CreateRole(string id)
        {
            _rolesService.Create(id);
            return RedirectToAction("Index");
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult DeleteRole(string id)
        {
            _rolesService.Delete(id);
            return RedirectToAction("Index");
        }

        public ViewResult Role(string id)
        {
            return View(new RoleViewModel
            {
                Role = id,
                Users = _rolesService.FindUserNamesByRole(id).Select(username => _userService.Get(username)).Where(p => p != null)
            });
        }

        public ViewResult Details(Guid id)
        {
            var user = _userService.Get(id);
            var userRoles = _rolesService.FindByUser(user);
            var roles = _rolesService.FindAll();

            if (roles.Distinct().Count() != roles.Count())
                throw new DuplicateRoleException("Список ролей содержит повторяющиеся значения.");

            ViewData["resMessage"] = TempData["resMessage"];
            return View(new DetailsViewModel
            {
                DisplayName = user.UserName,
                User = user,
                Roles = roles.ToDictionary(role => role, role => userRoles.Contains(role)),
                Status = user.IsOnline
                            ? StatusEnum.Online
                            : !user.IsApproved
                                ? StatusEnum.Unapproved
                                : user.IsLockedOut
                                    ? StatusEnum.LockedOut
                                    : StatusEnum.Offline
            });
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult Details(Guid id,
                                    [Bind(Prefix = "User.Email")] string email,
                                    [Bind(Prefix = "User.Comment")] string comment)
        {
            var user = _userService.Get(id);
            user.Email = email;
            user.Comment = comment;
            _userService.Update(user);
            return RedirectToAction("Details", new { id });
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult DeleteUser(Guid id)
        {
            MembershipUser muser = _userService.Get(id);

            string userLogin = muser.UserName;
            _userService.Delete(muser);

            return RedirectToAction("Index");
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult ChangeApproval(Guid id, bool isApproved)
        {
            var user = _userService.Get(id);
            user.IsApproved = isApproved;
            _userService.Update(user);
            return RedirectToAction("Details", new { id });
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult Unlock(Guid id)
        {
            _passwordService.Unlock(_userService.Get(id));
            return RedirectToAction("Details", new { id });
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult ResetPassword(Guid id, string answer)
        {
            var user = _userService.Get(id);
            var newPassword = _passwordService.ResetPassword(user, answer);

            var body = ResetPasswordBody + newPassword;
            _smtpClient.Send(new MailMessage(ResetPasswordFromAddress, user.Email, ResetPasswordSubject, body));

            return RedirectToAction("Details", new { id });
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult AddToRole(Guid id, string role)
        {
            // http://www.sql.ru/forum/actualthread.aspx?tid=609027
            _rolesService.AddToRole(_userService.Get(id), role);
            return RedirectToAction("Details", new { id });
        }

        // удалить из роли
        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult RemoveFromRole(Guid id, string role)
        {
            _rolesService.RemoveFromRole(_userService.Get(id), role);
            return RedirectToAction("Details", new { id });
        }

        public class DuplicateRoleException : ApplicationException
        {
            public DuplicateRoleException(string message)
                : base(message)
            {
            }
        }

        // получить список ролей
        public static string getRolesByUser(MembershipUser _user)
        {
            string rolesString = "", delimiter = "";
            IRolesService tempRolesService = new AspNetRoleProviderWrapper(Roles.Provider);
            var userRoles = tempRolesService.FindByUser(_user);
            foreach (var userRole in userRoles)
            {
                rolesString = rolesString + delimiter + userRole;
                delimiter = ", ";
            }

            return rolesString;

        }

        // получить параметры запроса
        private static string getParamString(string name)
        {
            return (System.Web.HttpContext.Current.Request[name] != null ? System.Web.HttpContext.Current.Request[name].ToString() : "");
        }

        //[AcceptVerbs(HttpVerbs.Post)]
        //public RedirectToRouteResult SavePartnerPrograms(Guid id, FormCollection formValues)
        //{
        //    var user = _userService.Get(id);
        //    return RedirectToAction("Details", new { id });
        //}
    }
}
